import os
import yaml
from pathlib import Path
from typing import Dict, Any, Optional

class Config:
    """配置管理类，提供配置文件的读取和解析功能"""
    
    def __init__(self, base_dir: Path):
        """初始化配置管理器
        
        Args:
            base_dir: 基础目录路径
        """
        self.base_dir = base_dir
        self.config_dir = base_dir / 'config'
        print(f"self.base_dir: {self.base_dir}, self.config_dir: {self.config_dir}")
        self.config_dir.mkdir(parents=True, exist_ok=True)
        self.config_data: Dict[str, Any] = {}
        
    def load_config(self, config_file: str = 'server_config.yaml') -> Dict[str, Any]:
        """加载配置文件
        
        Args:
            config_file: 配置文件名，默认为 server_config.yaml
            
        Returns:
            Dict[str, Any]: 配置数据字典
        """
        config_path = self.config_dir / config_file
        
        if not config_path.exists():
            raise FileNotFoundError(f"Configuration file not found: {config_path}")
            
        try:
            with open(config_path, 'r', encoding='utf-8') as f:
                self.config_data = yaml.safe_load(f) or {}
            return self.config_data
        except Exception as e:
            raise ValueError(f"Failed to load configuration: {e}")
            
    def get(self, key: str, default: Any = None) -> Any:
        """获取配置项
        
        Args:
            key: 配置项键名，支持点号分隔的多级键名
            default: 默认值
            
        Returns:
            Any: 配置项值
        """
        try:
            value = self.config_data
            for k in key.split('.'):
                value = value.get(k, {})
            return value if value != {} else default
        except Exception:
            return default
            
    def set(self, key: str, value: Any) -> None:
        """设置配置项
        
        Args:
            key: 配置项键名，支持点号分隔的多级键名
            value: 配置项值
        """
        keys = key.split('.')
        current = self.config_data
        
        for k in keys[:-1]:
            if k not in current:
                current[k] = {}
            current = current[k]
            
        current[keys[-1]] = value
        
    def save_config(self, config_file: str = 'server_config.yaml') -> None:
        """保存配置到文件
        
        Args:
            config_file: 配置文件名，默认为 server_config.yaml
        """
        config_path = self.config_dir / config_file
        
        try:
            with open(config_path, 'w', encoding='utf-8') as f:
                yaml.safe_dump(self.config_data, f, allow_unicode=True, default_flow_style=False)
        except Exception as e:
            raise ValueError(f"Failed to save configuration: {e}")
            
    def merge_config(self, new_config: Dict[str, Any]) -> None:
        """合并新的配置数据
        
        Args:
            new_config: 新的配置数据字典
        """
        def deep_merge(source: Dict, destination: Dict) -> Dict:
            for key, value in source.items():
                if key in destination:
                    if isinstance(value, dict) and isinstance(destination[key], dict):
                        deep_merge(value, destination[key])
                    else:
                        destination[key] = value
                else:
                    destination[key] = value
            return destination
            
        self.config_data = deep_merge(new_config, self.config_data)
        
    def validate_config(self, required_keys: Dict[str, type]) -> bool:
        """验证配置是否包含必需的键和类型
        
        Args:
            required_keys: 必需的键和对应的类型
            
        Returns:
            bool: 验证是否通过
        """
        def check_key_type(data: Dict, key: str, expected_type: type) -> bool:
            try:
                value = data
                for k in key.split('.'):
                    value = value[k]
                return isinstance(value, expected_type)
            except (KeyError, TypeError):
                return False
                
        for key, expected_type in required_keys.items():
            if not check_key_type(self.config_data, key, expected_type):
                return False
        return True 